/*
@hehung
email: 1398660197@qq.com
wechat: hehung95
reproduced and please indicate the source @hehung
*/


#include "app_common.h"
#include <time.h>


#define WIFI_DEBUG
#undef  WIFI_DEBUG

#ifdef WIFI_DEBUG
#include <stdio.h>
#define LOG(fmt, ...) 	          printf(fmt, ##__VA_ARGS__)
#else
#define LOG(fmt, ...)
#endif



static e_WifiOptType wifi_opt_mode = WIFI_OPT_INIT;
static e_WifiOptType wifi_opt_mode_pre = WIFI_OPT_INIT;

static e_WifiConnStaType wifi_conn_status = WIFI_DISCONNECT;
static e_WifiIotConnStaType wifi_iot_sttaus = WIFI_IOT_DISCONNECT;


static fsp_err_t Wifi_Setting(void);
static fsp_err_t Wifi_GetSntpTime(void);
static fsp_err_t Wifi_MqttSetting(void);
static fsp_err_t Wifi_MqttRunning(void);


/* WIFI setting */
static fsp_err_t Wifi_Setting(void)
{
	fsp_err_t status = FSP_ERR_ASSERTION;
	uint8_t resp_buf[512];
	
    status = Esp8266_ATCommandExe(ESP8266_ATCMD_IDX_ATE0, resp_buf);
    if(status != FSP_SUCCESS)
    {
		LOG("Wifi: ESP8266 echo off Failed!\r\n");
        return status;
    }
    DELAY_MS(1);
	
    status = Esp8266_ATCommandExe(ESP8266_ATCMD_IDX_STAMODE, resp_buf);
    if(status != FSP_SUCCESS)
    {
		LOG("Wifi: ESP8266 Set Station Command Failed!\r\n");
        return status;
    }
    DELAY_MS(1);
		
	/* Connect the new AP */
	status = Esp8266_ATCommandExe(ESP8266_ATCMD_IDX_HOTSPOT, resp_buf);
	if(status != FSP_SUCCESS)
	{
		LOG("Wifi: ESP8266 Connect hotspot Failed!\r\n");
		return status;
	}
    DELAY_MS(1);
	
    status = Esp8266_ATCommandExe(ESP8266_ATCMD_IDX_SINGLELINKMODE, resp_buf);
    if(status != FSP_SUCCESS)
    {
		LOG("Wifi: ESP8266 set single link mode Failed!\r\n");
        return status;
    }
    DELAY_MS(1);
	
	wifi_conn_status = WIFI_CONNECTED;
	
	return status;
}


static fsp_err_t Wifi_GetSntpTime(void)
{
	fsp_err_t status = FSP_ERR_ASSERTION;
	uint8_t resp_buf[512];
    char datetime[30];
	
	status = Esp8266_ATCommandExe(ESP8266_ATCMD_IDX_SNTPCFG, resp_buf);
	if(status != FSP_SUCCESS)
	{
		LOG("Wifi: ESP8266 Set time zone Failed!\r\n");
		return status;
	}
    DELAY_MS(20);
	
    do 
    {
        status = Esp8266_ATCommandExe(ESP8266_ATCMD_IDX_GETSNTPTIME, resp_buf);
        if(status != FSP_SUCCESS)
        {
            LOG("Wifi: ESP8266 Get time zone Failed!\r\n");
            return status;
        }
		
        // if year id "1970", indicate that wrong sntp time
        if (NULL == strstr((char*)resp_buf, "1970"))
        {
			uint8_t i;
			// Parse the time and write into the rtc
            for (i = 0; true; i++)
            {
                if (resp_buf[13+i] == '\n')
                    break;
                datetime[i] = resp_buf[13+i];
            }
			datetime[i] = '\0';
			LOG("+==Timer:%s\r\n", datetime);

			// Set time to RTC
			Rtc_SetTime(Rtc_StrtoTime(datetime));
            
            break;
        }
		
		DELAY_MS(500);
    } while (1);
    	
	
	return status;
}

static fsp_err_t Wifi_MqttSetting(void)
{
	fsp_err_t status = FSP_ERR_ASSERTION;
	uint8_t resp_buf[512];
	
	status = Esp8266_ATCommandExe(ESP8266_ATCMD_IDX_MQTTUSERCFG, resp_buf);
	if(status != FSP_SUCCESS)
	{
		LOG("Wifi: ESP8266 Configuration MQTT parameters Failed!\r\n");
		return status;
	}
    DELAY_MS(1);
	
	status = Esp8266_ATCommandExe(ESP8266_ATCMD_IDX_MQTTCONN, resp_buf);
	if(status != FSP_SUCCESS)
	{
		LOG("Wifi: ESP8266 Connect MQTT server Failed!\r\n");
		return status;
	}
    DELAY_MS(1);
	
	status = Esp8266_MqttSubscriber();
	if(status != FSP_SUCCESS)
	{
		LOG("Wifi: ESP8266 MQTT subscribe Failed!\r\n");
		return status;
	}
    DELAY_MS(1);
	
	wifi_iot_sttaus = WIFI_IOT_CONNECTED;
	
	return status;
}

static fsp_err_t Wifi_MqttRunning(void)
{
	fsp_err_t status = FSP_ERR_ASSERTION;
	uint8_t resp_buf[512];
	s_Hs300xDataType temp_humi = Hs300x_ReadData();
	s_postParamType post_data;
	BloodData max30102_samp_data = Max30102_GetSampleValue();
	
	post_data.temp = (float)temp_humi.temp;
	post_data.humi = (float)temp_humi.humi;
	post_data.mq5 = Mq5_GetGasPpmValue();
	post_data.mq5_thd = Warning_GetMq5Threshold();
	post_data.heart_beat = (uint8_t)max30102_samp_data.heart;
	post_data.spo2 = max30102_samp_data.SpO2;
	post_data.led = Led_GetDutyCycle_Led1();
	post_data.warning_switch = Warning_GetMq5WarningSwitch();
	
	Esp8266_MqttPost(&post_data);
	
	status = Esp8266_ATCommandExe(ESP8266_ATCMD_IDX_MQTTPUB, resp_buf);
	if(status != FSP_SUCCESS)
	{
		LOG("Wifi: ESP8266 Send MQTT parameters Failed!\r\n");
		return status;
	}
	
	
	return status;
}


/* WIFI operation mode */
static void Wifi_OperateModeManage(void)
{
    fsp_err_t err;

    switch(wifi_opt_mode)
    {
        case WIFI_OPT_SETTING:
        {
            err = Wifi_Setting();
            if(err)
            {
                LOG("\r\nWifi: Fail to setting\r\nRetry Start...\r\n");
                DELAY_MS(1000);
            }
            else
            {
                LOG("\r\nWifi: Sucess to setting\r\n");
                wifi_opt_mode_pre = wifi_opt_mode;
                wifi_opt_mode = WIFI_OPT_SNTP_SETTING;
            }
            
            break;
        }
		case WIFI_OPT_SNTP_SETTING:
		{
			err = Wifi_GetSntpTime();
			if (err)
			{
			    LOG("\r\nWifi: Fail to Get SNTP time\r\n");
                DELAY_MS(1000);
			}
			else
			{
                LOG("\r\nWifi: Sucess to Get SNTP time\r\n");
                wifi_opt_mode_pre = wifi_opt_mode;
                wifi_opt_mode = WIFI_OPT_MQTT_CONFIG;
			}
			break;
		}
		case WIFI_OPT_MQTT_CONFIG:
		{
			err = Wifi_MqttSetting();
			if (err)
			{
			    LOG("\r\nWifi: Fail to Configure the MQTT\r\n");
                DELAY_MS(1000);
			}
			else
			{
                LOG("\r\nWifi: Sucess to Configure the MQTT\r\n");
                wifi_opt_mode_pre = wifi_opt_mode;
                wifi_opt_mode = WIFI_OPT_WORKING;
			}
			break;
		}
		case WIFI_OPT_WORKING:
		{
			Wifi_MqttRunning();
			DELAY_MS(1000);
			break;
		}
        default:
        {
            LOG("Wifi: Error operation");
			DELAY_MS(1000);
            break;
        }
    }
}

void Wifi_Init(void)
{
	// Initialize the timer for WIFI counter
    g_timer0.p_api->open(g_timer0.p_ctrl, g_timer0.p_cfg);
    g_timer0.p_api->start(g_timer0.p_ctrl);
	
	Esp8266_Init();

	wifi_opt_mode = WIFI_OPT_SETTING;
    LOG("\r\nWifi: Wifi initialization success\r\n");
} 


/* Wifi working main interface for task */ 
void Wifi_RunningEntry(void)
{
    Wifi_OperateModeManage();
}

e_WifiConnStaType Wifi_GetApConnStatus(void)
{
	return wifi_conn_status;
}

e_WifiIotConnStaType Wifi_GetIotConnStatus(void)
{
	return wifi_iot_sttaus;
}
